﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
using System.Windows;
using System.Activities;

using ServiceLocator;
using WorkFlows;

namespace AppHost
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        private string NextWorkFlow = "Welcome";
        private object locker = new object();

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            Thread.CurrentThread.Name = "Main thread";
            MainWindow window = new MainWindow();
            window.DataContext = ServiceLocator.ServiceLocator.Instance.RepresentationLayerMain;
            window.Show();

            StartWorkFlow();
        }

        private void StartWorkFlow()
        {
            WorkflowApplication wfApp = InitiateWorkFlow();
            ServiceLocator.ServiceLocator.Instance.CurrentWorkFlow = wfApp;
            Action action = () => StartWorkFlow();

            wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs ev)
            {
                ReadOutputs(NextWorkFlow, ev);
                Dispatcher.Invoke(action); //call startworkflow() through main thread
            };

            wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs ev)
            {
                NextWorkFlow = "Welcome";
                Dispatcher.Invoke(action); //call startworkflow() through main thread
            };

            wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs ev)
            {
                Dispatcher.Invoke(action); //call startworkflow() through main thread
                Console.WriteLine(ev.UnhandledException.ToString());
                return UnhandledExceptionAction.Terminate;
            };

            wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs ev)
            {
                //nothing. workflow is waiting screen input, service call, or db call
            };

            wfApp.Run();
        }

        private WorkflowApplication InitiateWorkFlow()
        {
            WorkflowApplication wfApp = null;
            Dictionary<string, object> inputs;
            while (wfApp == null)
            {
                switch (NextWorkFlow)
                {
                    case "Welcome":
                        inputs = new Dictionary<string, object>() { };
                        wfApp = new WorkflowApplication(new WelcomeWorkFlow(), inputs);
                        break;
                    case "WithdrawCash":
                        inputs = new Dictionary<string, object>() { };
                        wfApp = new WorkflowApplication(new WithdrawCashWorkFlow(), inputs);
                        break;
                    case "CheckBalance":
                        inputs = new Dictionary<string, object>() { };
                        wfApp = new WorkflowApplication(new CheckBalanceWorkFlow(), inputs);
                        break;
                    default:
                        //Trace("Couldn't Identify workflow");
                        NextWorkFlow = "Welcome";
                        break;
                }
            }

            return wfApp;
        }

        private void ReadOutputs(string workflowName, WorkflowApplicationCompletedEventArgs e)
        {
            switch (workflowName)
            {
                case "Welcome":
                    NextWorkFlow = e.Outputs["ServiceArg"].ToString();
                    break;
                case "WithdrawCash":
                    NextWorkFlow = "Welcome";
                    bool wasCashWithdrawalSuccessful = Convert.ToBoolean(e.Outputs["IsSuccessful"]);
                    break;
                case "CheckBalance":
                    NextWorkFlow = "Welcome";
                    break;
                default:
                    //Trace("Couldn't Identify workflow");
                    NextWorkFlow = "Welcome";
                    break;
            }
        }
    }
}